import React, {memo, useEffect, useState} from 'react';
import {Link, Redirect} from "react-router-dom";
import {message} from "antd";
import {useDispatch, useSelector} from "react-redux";

import "./icon.css";
import "./index.css";
import request from "../../services/request";
import {
  calCqMean,
  calcTime,
  deepClone,
  getAnalysisInfo,
  getContextPath,
  getCurrentHours,
  getCurrentMinutes
} from "../../common/utils";
import {
  saveMachineLists,
  saveMachineWholeTimeStatus,
  saveMachineWorkStatus,
  saveNavigationIndex
} from "./store/actionCreators";
import {saveData} from "../../pages/main/store/actionCreators";
import {STATUS_NOT_WORK, STATUS_WORK} from "../../pages/main/run/config";
import {
  saveCurrentTempData,
  saveIsBell,
  saveMachineStatus,
  saveMeltData,
  savePauseCacheTime,
  savePcrData,
  saveRemainTime,
  saveRunPercent,
  saveRunStart,
  saveRunTime,
  saveStartTimeStamp,
  saveStopTime
} from "../../pages/main/run/store/actionCreators";
import * as axios from "q";
import {AMPLIFICATION, MELT} from "../../pages/main/protocol/config";
import {useSaveEndPointSetting} from "../../common/myHooks";
import {saveAnalysisShowLineArr} from "../../pages/main/plate/store/actionCreators";
import {saveIsRunToAnalysis} from "../../pages/main/analysis/store/actionCreators";
import {saveExperimentSetting} from "../../pages/main/analysis/components/geneExpression/store/actionCreators";
import {saveTargetSelectedArr} from "../../pages/main/analysis/components/quantification/store/actionCreators";

let statusTimeout;
export default memo(function Navigation(props) {
  const dispatch = useDispatch();
  const {
    data,
    pauseCacheTime,
    startTimeStamp,
    runStart,
    machineWholeTimeStatus,
    currentTempData,
    userInfo,
    machineList,
    navigationIndex,
    stages,
    openBell,
    isCN,
    multiData
  } = useSelector(state => ({
    data: state.dataReducer.data,
    runStart: state.runReducer.runStart,
    startTimeStamp: state.runReducer.startTimeStamp,//  开始实验的时间戳
    pauseCacheTime: state.runReducer.pauseCacheTime, //  暂停时缓存运行时间
    machineWholeTimeStatus: state.navigationReducer.machineWholeTimeStatus, //  连接仪器时不断轮询的仪器状态
    currentTempData: state.runReducer.currentTempData,
    userInfo: state.loginReducer.info,  //  获得用户信息
    machineList: state.navigationReducer.machineLists,
    navigationIndex: state.navigationReducer.navigationIndex,
    stages: state.protocolReducer.stages,
    openBell: state.runReducer.openBell,
    isCN: state.languageReducer.isCN,
    multiData: state.analysisReducer.multiData
  }));
  const {isShow, go, navItem, subTitle, iconStyle, mainProps} = props; //  获得父组件传递过来的值
  const [navIndex, setNavIndex] = useState(0);  //  导航点击索引
  const [url, setUrl] = useState("");
  const [count, setCount] = useState(0);
  let cloneMachineList = [];  //  保证machineList的不可变性,克隆一个新数组
  let pcrControl = stages.some(item => item.state === AMPLIFICATION); //  protocol界面是否由AMPLIFICATION
  let meltControl = stages.some(item => item.state === MELT); //  protocol界面是否由MELT
  let cloneData = {};
  let data_sampleTemperature = [];
  let data_lidTemperature = [];
  const saveEndPointSetting = useSaveEndPointSetting();

  useEffect(() => {
    if (!url) {
      return;
    }
    let iframe = document.createElement("iframe");
    iframe.src = url;
    iframe.style.display = "none";
    document.body.appendChild(iframe);
    setTimeout(() => iframe.remove(), 1000);
  }, [url]);

  useEffect(() => {
    setNavIndex(Number(sessionStorage.getItem("sessionNavIndex"))); //  session中的索引改变时切换导航栏的选中目标
  }, [Number(sessionStorage.getItem("sessionNavIndex"))]);

  useEffect(() => {
    // request({
    //   url: "/downloadAction/readPreferences",
    //   method: "get"
    // }).then(res => {
    // }).catch(err => {
    //   message.warn(err);
    // });
    searchMachine();  //  执行一次搜索仪器
    setNavIndex(Number(sessionStorage.getItem("sessionNavIndex"))); //  获取session中的导航索引
  }, []);

  useEffect(() => {
    setNavIndex(navigationIndex);
  }, [navigationIndex]);

  useEffect(() => {
    dispatch(saveMachineWorkStatus(machineWholeTimeStatus.status));
    if (machineWholeTimeStatus.workStatus === STATUS_WORK) {
      setCount(count + 1);
      dispatch(saveRunStart(true));
      dispatch(saveRunPercent((1 - machineWholeTimeStatus.programTimeRemain / (Math.floor((Date.now() - startTimeStamp) / 1000) + pauseCacheTime + machineWholeTimeStatus.programTimeRemain)) * 100)); //  设置运行进度条
      dispatch(saveRemainTime(calcTime(machineWholeTimeStatus.programTimeRemain)));  //  设置剩余时间
      // console.log(machineWholeTimeStatus)
      dispatch(saveRunTime(calcTime(Math.floor((Date.now() - startTimeStamp) / 1000) + pauseCacheTime))); //  设置运行时间
      // console.log(startTimeStamp, calcTime(pauseCacheTime), "runTime:", calcTime(Math.floor((Date.now() - startTimeStamp) / 1000) + pauseCacheTime))
      let runTesTime = calcTime(Math.floor((Date.now() - startTimeStamp) / 1000) + pauseCacheTime);
      let tempTime = new Date(startTimeStamp);
      // console.log(machineWholeTimeStatus, data, pauseCacheTime,tempTime)
      if (Number(runTesTime) === 0) {
        // console.log("bug:", machineWholeTimeStatus, data, pauseCacheTime,tempTime)
      }
      //  设置温度
      let timestamp = new Date().getTime();
      currentTempData.push({
        timestamp,
        sample: machineWholeTimeStatus.sampleTemperature[1] / 100,
        lid: machineWholeTimeStatus.hotLidTemperature / 100
      });
      dispatch(saveCurrentTempData(JSON.parse(JSON.stringify(currentTempData))));
      dispatch(saveMachineStatus(machineWholeTimeStatus));
      cloneData = deepClone(data, cloneData);
      if (count % 20 === 0) {
        pcrControl && request({
          url: 'deviceAction/getPCRData',
          data: data.connectPort,
          method: 'post',
          forbiddenLogo: true
        })
          .then(res => {
            dispatch(savePcrData(res));
            cloneData.wells.forEach(item => {
              const azdIndex = item.col * 8 + item.row; //  AZD中的数据是竖着算的,D3对应19,cqa中D3对应38
              //  将quantification原始数据存入data大对象
              item.lines[0].quantificationOrigin = res['channel1'][azdIndex];
              item.lines[1].quantificationOrigin = res['channel2'][azdIndex];
              item.lines[2].quantificationOrigin = res['channel3'][azdIndex];
              item.lines[3].quantificationOrigin = res['channel4'][azdIndex];
              item.lines[4].quantificationOrigin = res['channel5'][azdIndex];
              item.lines[5].quantificationOrigin = res['channel6'][azdIndex];
            });
            dispatch(saveTargetSelectedArr(cloneData.targets.map(item => item.name)));
            dispatch(saveData(cloneData));
          })
          .catch(err => message.error(err));

        meltControl && request({
          url: 'deviceAction/getMeltData',
          data: data.connectPort,
          method: 'post',
          forbiddenLogo: true
        })
          .then(res => dispatch(saveMeltData(res)))
          .catch(err => message.error(err));
      }
      if (!pcrControl && !meltControl) {  //  没有pcr和melt
        dispatch(saveTargetSelectedArr(data.targets.map(item => item.name)));
        dispatch(saveData({...data}));
      }
    } else if (runStart && machineWholeTimeStatus.workStatus === STATUS_NOT_WORK) {
      setCount(0);
      setUrl("");
      dispatch(saveStopTime(`${getCurrentHours()}:${getCurrentMinutes()}`));
      dispatch(saveRunStart(false));
      dispatch(saveRunPercent(100));
      dispatch(saveIsBell(true));
      dispatch(saveRemainTime(calcTime(0)));
      dispatch(savePauseCacheTime(0));
      currentTempData.forEach(item => {
        data_sampleTemperature.push({time: item.timestamp, temperature: item.sample});
        data_lidTemperature.push({time: item.timestamp, temperature: item.lid});
      });
      cloneData = deepClone(data, cloneData);
      if (pcrControl || meltControl) {  //  有pcr或melt
        let pcrRequest = request({ //  请求pcr数据
          url: 'deviceAction/getPCRData',
          data: data.connectPort,
          method: 'post',
          forbiddenLogo: true
        });
        let meltRequest = request({ //  请求melt数据
          url: 'deviceAction/getMeltData',
          data: data.connectPort,
          method: 'post',
          forbiddenLogo: true
        });
        //  pcr和melt都请求完成后请求计算全部分析数据
        setTimeout(function () {
          axios.all([pcrRequest, meltRequest]).then(res => {
            cloneData.pcrDataOrigin = res[0];
            for (let i = 0; i < res[1].length; i++) {
              for (let j = 1; j < res[1][i].length - 1; j++) {
                if (res[1][i][j] === 0) {
                  res[1][i][j] = (res[1][i][j-1] + res[1][i][j+1]) / 2;
                }
              }
            }
            cloneData.meltDataOrigin = res[1];
            cloneData.wells.forEach(item => {
              const azdIndex = item.col * 8 + item.row; //  AZD中的数据是竖着算的,D3对应19,cqa中D3对应38
              //  将quantification原始数据存入data大对象
              item.lines[0].quantificationOrigin = res[0]['channel1'][azdIndex];
              item.lines[1].quantificationOrigin = res[0]['channel2'][azdIndex];
              item.lines[2].quantificationOrigin = res[0]['channel3'][azdIndex];
              item.lines[3].quantificationOrigin = res[0]['channel4'][azdIndex];
              item.lines[4].quantificationOrigin = res[0]['channel5'][azdIndex];
              item.lines[5].quantificationOrigin = res[0]['channel6'][azdIndex];
              //  TODO: well中的meltData应该是一个一维数组,出现了96个孔的melt数据都存到了一个meltData里面的情况,暂不清楚产生原因
              res[1].length > 0 && (item.meltData = res[1][azdIndex]);  //  将meltData原始数据存入data大对象

              //TODO:well的meltData必须为一维数组，且数据对应，检查转换为正确数据
              if (Array.isArray(item.meltData[0])) {
                console.warn('硬件端仪器保存cqa-meltData数据异常');
                const meltDataOrigin = cloneData.meltDataOrigin;
                item.meltData = meltDataOrigin[azdIndex];
              }
              for (let i = 1; i < item.meltData.length - 1; i++) {
                if (item.meltData[i] === 0) {
                  item.meltData[i] = (item.meltData[i - 1] + item.meltData[i + 1]) / 2;
                }
              }
            });
            request({
              url: 'analysis/calAll',
              data: cloneData,
              method: 'post'
            })
              .then(res => {
                switch (res.code) {
                  case 200:
                    // 运行结束后自动保存Cqa文件
                    request({
                      url: 'downloadAction/downloadAll',
                      data: {
                        experimentName: res.data.experimentName,
                        userName: res.data.userName,
                        data: JSON.stringify({
                          ...res.data,
                          sampleTemperature: data_sampleTemperature,
                          lidTemperature: data_lidTemperature,
                          connectPort: ""
                        })
                      },
                      method: 'post'
                    }).then(() => {
                      setUrl(getContextPath() + "/downloadAction/downloadAllUrl");
                    }).catch(err => message.error(err));
                    //  保存data
                    calCqMean(res.data);  //  重新计算 cqMean
                    //TODO:sample颜色丢失
                    cloneData.wells.forEach((item, index) => res.data.wells[index].sampleColor = item.sampleColor);
                    //data.targets与data.plateSetting不一致,标曲线消失
                    res.data.targets.forEach(it => {
                      // it.opt = true;    //跳转opt勾选
                      const index = res.data.plateSetting.targets.findIndex(t => t.name === it.name);
                      if (index === -1) {
                        return;
                      }
                      res.data.plateSetting.targets[index] = it;  //同步两个target,解决标曲线消失
                    });
                    dispatch(saveTargetSelectedArr(res.data.targets.map(item => item.name)));//target opt勾上
                    // 加载cqa文件后更新geneExpression界面的experimentSetting
                    let experimentSetting = {
                      targets: [],
                      samples: []
                    };
                    res.data.plateSetting.targets.forEach(item => {
                      experimentSetting.targets.push({
                        name: item.name,
                        control: false,
                        color: item.color,
                        e: item.e > 0 ? item.e : 1,
                        showChart: true
                      });
                    });
                    res.data.plateSetting.samples.forEach(item => {
                      experimentSetting.samples.push({
                        name: item.name,
                        reference: false,
                        color: item.color,
                        showChart: true,
                        type: item.type
                      });
                    });
                    dispatch(saveExperimentSetting(experimentSetting));
                    dispatch(saveData({
                      ...res.data,
                      sampleTemperature: data_sampleTemperature,
                      lidTemperature: data_lidTemperature
                    }));
                    saveEndPointSetting(res.data);  //  实验结束后进行计算用data信息来保存终点法相关数据
                    dispatch(saveAnalysisShowLineArr(getAnalysisInfo(res.data).analysisShowLineArr)); //  保存可以画线的数据(只有target和sample同时选择后才能画线)
                    dispatch(saveNavigationIndex(4)); //  改变导航栏选中
                    mainProps.history.push("/main/analysis"); //  跳转到分析界面
                    break;
                  case 500:
                    message.error(res.message);
                    break;
                  default:
                    message.error("error");
                    // TODO: 排查错误
                    console.log(res);
                }
              })
              .catch(err => message.error(err));
          }).catch(err => message.error(err));
        }, 3500);
      }
      if (!pcrControl && !meltControl) {  //  没有pcr和melt
        dispatch(saveTargetSelectedArr(data.targets.map(item => item.name)));
        dispatch(saveData({
          ...data,
          sampleTemperature: data_sampleTemperature,
          lidTemperature: data_lidTemperature
        }));
        dispatch(saveNavigationIndex(4)); //  改变导航栏选中
        mainProps.history.push("/main/analysis"); //  跳转到分析界面
      }
      dispatch(saveIsBell(openBell)); //  开启闹铃功能后设置响铃
    } else {
      // console.log("暂停时：",machineWholeTimeStatus,new Date(startTimeStamp))
      dispatch(saveStartTimeStamp(Date.now()));
    }
  }, [machineWholeTimeStatus]);

  function homeBtnClick() {   //  通过show方法把true传递给父组件
    isShow(true);
  }

  function itemClick(item, indey) {
    dispatch(saveNavigationIndex(indey));
    sessionStorage.setItem("sessionNavIndex", indey);
    setNavIndex(indey);
  }

  //  搜索仪器
  function searchMachine() {
    // console.log(data);
    request({
      url: "/deviceAction/search",
      method: "get"
    }).then(res => {
      switch (res.code) {
        case 200:
          let searchedMachines = res.data.filter(item => {  //  只搜索到未连接状态的仪器
            // if (item.status !== "connect") {
            return item;
            // }
          });
          // TODO:关闭软件后connectPort就自动清空了
          // res.data.some(it => it.connectPort === data.connectPort && searchedMachines.push(it));  //  通过connectPort一致来确定当前软件已经连接了仪器,那么尽管该仪器状态是已连接也要搜索到此仪器
          searchedMachines.forEach(it => it.status = 'disconnect'); //  每次搜索仪器不管仪器状态如何前端都要显示未连接
          dispatch(saveMachineLists(searchedMachines.length === 0 ? [{
            id: 0,
            name: "N/A"
          }] : searchedMachines));
          break;
        case 500:
          message.error(res.message);
          break;
        default:
          message.error("error");
          // TODO: 排查错误
          console.log(res);
      }
    }).catch(msg => {
      message.error(msg);
    });
  }

  //  连接或断开仪器
  // function connectMachine(item, indey) {
  //   clearInterval(statusTimeout);
  //   cloneMachineList = deepClone(machineList, cloneMachineList);  //  不能在search中克隆,因为异步机制导致cloneMachineList的值在全局拿不到
  //   if (item.status === "disconnect") {
  //     //1.connect
  //     //2.disconnect
  //     //3.connect
  //     request({
  //       url: "/deviceAction/connect",
  //       data: item.connectPort,
  //       method: "post"
  //     }).then(res => {
  //       switch (res.code) {
  //         case 200:
  //           if (res.data) {
  //             isCN
  //               ? message.info("连接成功")
  //               : message.info("Successful connection");
  //             cloneMachineList[indey].status = "connect";
  //             dispatch(saveMachineLists(cloneMachineList));
  //             dispatch(saveData({
  //               ...data,
  //               connectPort: item.connectPort,
  //               coefficients: cloneMachineList[indey].coefficients
  //             }));
  //             statusTimeout = setInterval(() => {
  //               request({
  //                 url: 'deviceAction/getStatus',
  //                 data: item.connectPort,
  //                 method: 'post',
  //                 forbiddenLogo: true
  //               }).then(res => {
  //                 dispatch(saveMachineWholeTimeStatus(res));
  //               }).catch(err => {
  //                 message.error(err);
  //                 clearInterval(statusTimeout);
  //                 console.log("获取状态失败,可能原因:连接断开");
  //               });
  //             }, 1000);
  //           } else {
  //             isCN
  //               ? message.info("连接失败")
  //               : message.error("Failed to connect");
  //           }
  //           break;
  //         case 500:
  //           message.error(res.message);
  //           break;
  //         default:
  //           message.error("error");
  //           // TODO: 排查错误
  //           console.log(res);
  //       }
  //     }).catch(msg => {
  //       message.error(msg);
  //     });
  //   } else {
  //     request({
  //       url: "/deviceAction/disconnect",
  //       data: item.connectPort,
  //       method: "post"
  //     }).then(() => {
  //       message.info("disconnected");
  //       cloneMachineList[indey].status = "disconnect";
  //       dispatch(saveMachineLists(cloneMachineList));
  //       dispatch(saveData({...data, connectPort: ""}));
  //     }).catch(msg => {
  //       message.error(msg);
  //     });
  //   }
  // }
  //  连接或断开仪器
  //连接断开再重连处理，解决每次浏览器关闭前未先断开连接，导致下次打开连接问题残留
  function connectMachine(item, indey) {
    clearInterval(statusTimeout);
    cloneMachineList = deepClone(machineList, cloneMachineList);  //  不能在search中克隆,因为异步机制导致cloneMachineList的值在全局拿不到
    if (item.status === "disconnect") {
      request({
        url: "/deviceAction/connect",
        data: item.connectPort,
        method: "post"
      }).then(res => {
        switch (res.code) {
          case 200:
            request({
              url: "/deviceAction/disconnect",
              data: item.connectPort,
              method: "post"
            }).then(() => {
              request({
                url: "/deviceAction/connect",
                data: item.connectPort,
                method: "post"
              }).then(res => {
                switch (res.code) {
                  case 200:
                    if (res.data) {
                      isCN
                        ? message.info("连接成功")
                        : message.info("Successful connection");
                      cloneMachineList[indey].status = "connect";
                      dispatch(saveMachineLists(cloneMachineList));
                      dispatch(saveData({
                        ...data,
                        connectPort: item.connectPort,
                        coefficients: cloneMachineList[indey].coefficients
                      }));
                      statusTimeout = setInterval(() => {
                        request({
                          url: 'deviceAction/getStatus',
                          data: item.connectPort,
                          method: 'post',
                          forbiddenLogo: true
                        }).then(res => {
                          dispatch(saveMachineWholeTimeStatus(res));
                        }).catch(err => {
                          message.error(err);
                          clearInterval(statusTimeout);
                          console.log("获取状态失败,可能原因:连接断开");
                        });
                      }, 1000);
                    } else {
                      isCN
                        ? message.info("连接失败")
                        : message.error("Failed to connect");
                    }
                    break;
                  case 500:
                    message.error(res.message);
                    break;
                  default:
                    message.error("error");
                    // TODO: 排查错误
                    console.log(res);
                }
              }).catch(msg => {
                message.error(msg);
              });
            }).catch(msg => {
              message.error(msg);
            });
            break;
          case 500:
            message.error(res.message);
            break;
          default:
            message.error("error");
            // TODO: 排查错误
            console.log(res);
        }
      }).catch(msg => {
        message.error(msg);
      });
    } else {
      request({
        url: "/deviceAction/disconnect",
        data: item.connectPort,
        method: "post"
      }).then(() => {
        message.info("disconnected");
        cloneMachineList[indey].status = "disconnect";
        dispatch(saveMachineLists(cloneMachineList));
        dispatch(saveData({...data, connectPort: ""}));
      }).catch(msg => {
        message.error(msg);
      });
    }
  }

  function controlTray() {

  }


  return go ? <Redirect to="/home"/> : (
    <nav className="nav">
      <div style={{height: "500px"}}>
        <div className="navTitle">cqMAN</div>
        {subTitle ? <div className="settingTitle">
          <div/>
          <div>{subTitle}</div>
        </div> : null}
        <ul>
          {navItem.map((item, index) =>
            (
              <Link key={item.content} to={item.path} replace>
                <li className={"navItem " + (index === navIndex ? "activeNav" : "")}
                    onClick={() => itemClick(item, index)}>
                  <div className={item.iconStyle + " " + iconStyle}/>
                  <div>{item.content}</div>
                </li>
              </Link>
            )
          )}
        </ul>
      </div>
      <div className="navOperation">
        {/*点击后会弹出自定义的对话框,点击确定将页面重定向到首页,点击取消则留在当前页面*/}
        <div onClick={homeBtnClick} className="navHome">
          <div className="icon-home"/>
          <div>{isCN ? "首页" : "HOME"}</div>
        </div>
        <div onClick={searchMachine} className="navSearch">
          <div className="icon-wifi"/>
          <div>{isCN ? "搜索仪器" : "Search"}</div>
        </div>
        <ul className="navMachineList">
          {machineList.map((item, index) =>
            (
              <li key={item.id}>
                <div className="icon-machine"/>
                <div>{item.name}</div>
                <div onClick={() => connectMachine(item, index)}
                     className={(item.status === "connect" ? "machineConnected" : "")}/>
              </li>
            )
          )}
        </ul>
        <div className="navUser">
          {
            userInfo.portrait ? <div style={{backgroundImage: `url(${userInfo.portrait})`}}/> : <div/>
          }
          <div>{isCN ? "你好" : "Hello"}</div>
          <div>{userInfo.username}</div>
        </div>
      </div>
    </nav>
  );
});
